// Copyright (c) 2023 CHANGLEI. All rights reserved.

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:tverify/src/ui_decorator.dart';
import 'package:tverify/tverify_platform_interface.dart';

/// An implementation of [TverifyPlatform] that uses method channels.
class MethodChannelTverify extends TverifyPlatform {
  /// An implementation of [TverifyPlatform] that uses method channels.
  MethodChannelTverify() {
    methodChannel.setMethodCallHandler(_handleMethod);
  }

  /// The method channel used to interact with the native platform.
  @visibleForTesting
  final methodChannel = const MethodChannel('tverify');
  final _clickListeners = <String, VoidCallback>{};
  final _checkboxCheckedListeners = ObserverList<ValueChanged<Map<String, dynamic>?>>();
  final _loginClickCompleteListeners = ObserverList<ValueChanged<Map<String, dynamic>?>>();
  final _loginClickStartListeners = ObserverList<ValueChanged<Map<String, dynamic>?>>();
  final _checkboxCheckedChangeListeners = ObserverList<ValueChanged<bool>>();
  final _authLoginListeners = ObserverList<VoidCallback>();
  final _pressBackListeners = ObserverList<VoidCallback>();

  @override
  Future<void> initLogin(String appId) async {
    await methodChannel.invokeMethod<void>(
      'initLogin',
      <String, dynamic>{
        'appId': appId,
      },
    );
  }

  @override
  Future<Map<String, dynamic>?> preLogin() async {
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'preLogin',
    );
    return result?.cast<String, dynamic>();
  }

  @override
  Future<Map<String, dynamic>?> login(UIDecorator decorator) async {
    _clickListeners.clear();
    _clickListeners.addAll(decorator.allCallbacks);
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'login',
      decorator.toMap(),
    );
    return result?.cast<String, dynamic>();
  }

  @override
  Future<Map<String, dynamic>?> getSimInfo() async {
    final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>(
      'getSimInfo',
    );
    return result?.cast<String, dynamic>();
  }

  @override
  Future<bool?> deleteScrip() {
    return methodChannel.invokeMethod<bool>(
      'deleteScrip',
    );
  }

  @override
  Future<void> setTimeout(Duration duration) {
    return methodChannel.invokeMethod<void>(
      'setTimeout',
      <String, dynamic>{
        'duration': duration.inMilliseconds.toDouble(),
      },
    );
  }

  @override
  Future<void> dismissLogin([bool animated = true]) {
    return methodChannel.invokeMethod<void>(
      'dismissLogin',
      <String, dynamic>{
        'animated': animated,
      },
    );
  }

  @override
  Future<String?> getNetworkType() {
    return methodChannel.invokeMethod<String>(
      'getNetworkType',
    );
  }

  @override
  Future<String?> getOperatorType() {
    return methodChannel.invokeMethod<String>(
      'getOperatorType',
    );
  }

  @override
  Future<void> certificationNumber(String number) {
    return methodChannel.invokeMethod(
      'certificationNumber',
      <String, dynamic>{
        'number': number,
      },
    );
  }

  @override
  Future<void> setDebugModel(bool isDebug) {
    return methodChannel.invokeMethod(
      'setDebugModel',
      <String, dynamic>{
        'isDebug': isDebug,
      },
    );
  }

  @override
  Future<void> setLoginBtn(String text) {
    return methodChannel.invokeMethod(
      'setLoginBtn',
      <String, dynamic>{
        'text': text,
      },
    );
  }

  @override
  Future<void> setSecondPrivacyCallback(bool isCallback) {
    return methodChannel.invokeMethod(
      'setSecondPrivacyCallback',
      <String, dynamic>{
        'isCallback': isCallback,
      },
    );
  }

  @override
  void addCheckboxCheckedListener(ValueChanged<Map<String, dynamic>?> callback) {
    _checkboxCheckedListeners.add(callback);
  }

  @override
  void addLoginClickCompleteListener(ValueChanged<Map<String, dynamic>?> callback) {
    _loginClickCompleteListeners.add(callback);
  }

  @override
  void addLoginClickStartListener(ValueChanged<Map<String, dynamic>?> callback) {
    _loginClickStartListeners.add(callback);
  }

  @override
  void addCheckboxCheckedChangeListener(ValueChanged<bool> callback) {
    _checkboxCheckedChangeListeners.add(callback);
  }

  @override
  void addAuthLoginListener(VoidCallback callback) {
    _authLoginListeners.add(callback);
  }

  @override
  void addPressBackListener(VoidCallback callback) {
    _pressBackListeners.add(callback);
  }

  @override
  void removeCheckboxCheckedListener(ValueChanged<Map<String, dynamic>?> callback) {
    _checkboxCheckedListeners.remove(callback);
  }

  @override
  void removeLoginClickCompleteListener(ValueChanged<Map<String, dynamic>?> callback) {
    _loginClickCompleteListeners.remove(callback);
  }

  @override
  void removeLoginClickStartListener(ValueChanged<Map<String, dynamic>?> callback) {
    _loginClickStartListeners.remove(callback);
  }

  @override
  void removeCheckboxCheckedChangeListener(ValueChanged<bool> callback) {
    _checkboxCheckedChangeListeners.remove(callback);
  }

  @override
  void removeAuthLoginListener(VoidCallback callback) {
    _authLoginListeners.remove(callback);
  }

  @override
  void removePressBackListener(VoidCallback callback) {
    _pressBackListeners.remove(callback);
  }

  Future<void> _handleMethod(MethodCall call) async {
    switch (call.method) {
      case 'onClickListener':
        _clickListeners[call.arguments['id'] as String]?.call();
      case 'onCheckboxChecked':
        for (final value in List.of(_checkboxCheckedListeners)) {
          value((call.arguments as Map<dynamic, dynamic>?)?.cast<String, dynamic>());
        }
      case 'onLoginClickComplete':
        for (final value in List.of(_loginClickCompleteListeners)) {
          value((call.arguments as Map<dynamic, dynamic>?)?.cast<String, dynamic>());
        }
      case 'onLoginClickStart':
        for (final value in List.of(_loginClickStartListeners)) {
          value((call.arguments as Map<dynamic, dynamic>?)?.cast<String, dynamic>());
        }
      case 'onCheckboxCheckedChange':
        for (final value in List.of(_checkboxCheckedChangeListeners)) {
          value(call.arguments as bool);
        }
      case 'onAuthLoginListener':
        for (final value in List.of(_authLoginListeners)) {
          value();
        }
      case 'onPressBackListener':
        for (final value in List.of(_pressBackListeners)) {
          value();
        }
    }
  }
}
